iT邦幫忙

2026 iThome 鐵人賽

DAY 25
0
Software Development

遠古聖遺物改造工程:遺留系統全面重構實務指南系列 第 25

[Day 25] 系統能承受多少負載?應該如何進行壓力測試?

  • 分享至 

  • xImage
  •  

系統能承受多少負載?應該如何進行壓力測試?

前面章節已確認目標系統的功能、部署方式與跨服務互動。如果系統在單次操作時能正確回應,仍不能推論它在多項工作同時發生時可以維持相同結果。等待時間可能逐步增加,工作佇列可能持續累積,相依項目也可能在大量重試後失效。

效能測試要回答一個有條件的問題:在指定環境、資料規模、操作組合與持續時間下,系統能否在驗收門檻內完成工作,超過容量後又會如何失敗及恢復。這些條件缺少任何一項,「系統每秒可以處理多少工作」都只是一個無法重現的數字。

先把效能需求改寫成驗收條件

「回應要快」與「系統要能承受尖峰」沒有明確限制,無法決定測試負載、持續時間及通過標準。開始撰寫腳本前,應該先根據已核准需求記錄下列內容:

確認面向 要定義的條件 可檢查結果
工作負載 每秒操作數、同時執行數、操作比例、資料規模及持續時間 測試實際產生的負載符合指定範圍
回應時間 每類操作的平均值、第 95 與第 99 百分位限制 指定比例的操作在時間門檻內完成
吞吐量 單位時間內必須完成的有效工作數量 完成量達到需求,且沒有以大量錯誤換取表面數字
錯誤比例 可接受的逾時、拒絕及失敗比例 測試期間各類錯誤沒有超過個別門檻
資料結果 負載期間與測試後必須維持的功能及保存結果 已完成操作的輸出、狀態變化與外部效果通過驗證
積壓限制 佇列或待處理工作的數量與最長等待時間 積壓沒有持續成長,或能在限制時間內清除
恢復時間 負載下降或相依項目恢復後,多久要回到正常範圍 回應、錯誤與積壓在期限內恢復

吞吐量(Throughput)代表單位時間內完成的有效工作數量,不能只計算已送入系統的操作。接受工作後長期停留在佇列,或以錯誤結果快速結束,都不構成有效完成量。

效能基準記錄某個版本在固定條件下的結果,驗收門檻則來自目標需求。遺留系統的既有表現可以作為比較起點,但如果它本來就無法滿足需求,不能直接成為目標系統的通過標準。

從實際紀錄建立工作負載模型

測試情境要反映系統真正會執行的工作。可以從執行紀錄、排程、功能統計與已確認的使用方式整理一般時段、尖峰時段及特殊批次的操作組合:

  • 記錄每類操作在不同時段的數量、比例、執行時間與錯誤情況。
  • 區分互動操作、背景工作、排程工作與訊息消費,避免只測量單一入口。
  • 記錄資料總量、常見資料大小、熱門與冷門資料分布,以及會影響處理路徑的狀態。
  • 確認操作之間是否具有固定順序、等待時間、重試或前一步輸出。
  • 將一般負載、預期尖峰、短時間突增及長時間持續工作分成不同設定檔。
  • 移除正式敏感內容,改用能重現相同資料特徵的測試資料。

如果目標系統包含既有系統沒有的新功能,就要按照已核准的預期使用量建立假設,記錄假設來源及重新評估條件。缺少歷史紀錄時,可以先測量多組範圍,不能把最有利的一組結果當成未來容量。

工作負載模型也要區分到達率與同時執行數。每秒進入十項工作,不代表系統同時只處理十項。當回應變慢,尚未完成的工作會增加,同時執行數也會跟著上升。兩者混用會讓測試在系統變慢時自動降低輸入,掩蓋真正的過載情況。

區分不同效能測試的目的

效能測試是涵蓋多種測試目的的上位概念。ISTQB 效能測試教材分別定義負載、壓力、尖峰與耐久等測試,每一種回答的問題不同。

測試類型 負載方式 要回答的問題 主要觀察結果
負載測試(Load Testing) 在預期與尖峰範圍內逐步增加或維持工作量 系統能否在預定負載下持續符合驗收門檻 回應時間、吞吐量、錯誤比例、積壓與執行資源餘裕
壓力測試(Stress Testing) 提高到預期範圍以上,直到門檻失守或觸發停止條件 容量上限在哪裡,超載時會如何失敗 最大穩定負載、第一個瓶頸、拒絕方式與恢復時間
尖峰測試(Spike Testing) 在短時間內快速提高工作量,再降回正常範圍 突發工作是否造成失控積壓或連鎖失敗 瞬間錯誤、排隊時間、降級結果及恢復速度
耐久測試(Soak Testing) 在代表性負載下持續執行符合實際情境的長時間 長時間運作是否出現累積性退化 資源持續成長、連線未釋放、垃圾回收停頓、積壓與效能漂移

四種測試可以共用功能流程與量測方式,但負載形狀、持續時間及通過條件要分開保存。短時間負載測試通過,不足以證明長時間穩定。壓力測試找到失敗點,也不表示預期負載已經通過驗收。

建立隔離且可比較的測試環境

高負載測試可能耗用大量執行資源、產生保存資料,並且觸發相依項目的限制。預設應該在獨立環境執行,並使容量相關設定盡量接近預定部署環境:

  • 固定系統版本、設定、執行單位數量、相依項目版本與容量限制。
  • 隔離其他不屬於測試的工作,並記錄無法隔離的背景活動。
  • 使用可重複建立的資料集,讓每次測試從相同資料量與狀態開始。
  • 明確標示哪些相依項目使用真實測試實例,哪些使用具有固定延遲與錯誤行為的替代項目。
  • 將負載產生器與受測系統分開,確認產生器仍有足夠餘裕,沒有先成為限制來源。
  • 對外部相依項目取得明確測試授權,未取得授權時應該排除或替代,避免把負載轉嫁到範圍外系統。

如果測試環境的容量或拓撲與預定部署環境不同,結果只能代表目前環境。從縮小環境直接等比例推算正式容量,可能忽略共享限制、固定成本與非線性瓶頸,必須另外驗證推算方式。

正式環境中的有限測試只有在風險已核准、範圍可控制且具備停止條件時才能進行。測試前要限制對正式資料與其他使用對象的影響,並確認監控、通知及復原流程已經就緒。

將測試情境寫成可重複規格

測試腳本只描述如何執行,完整情境還要記錄輸入資料、負載階段、預期結果與停止條件。遺留系統和目標系統應該共用相同案例識別碼與比較格式。

情境欄位 應記錄的內容
案例識別碼 使用穩定名稱,例如 PERF-READ-01,讓兩套系統與歷次結果可以對照
功能流程 每一步輸入、等待、狀態相依及預期輸出
資料版本 測試資料集、初始狀態、資料量與重建方式
負載模型 到達率或同時執行數、操作比例及各階段持續時間
測試階段 腳本確認、暖機、逐步增加、穩定執行、降載及恢復觀察
驗收門檻 回應時間百分位、吞吐量、錯誤比例、積壓與資料正確性
停止條件 錯誤、等待、積壓或資源狀態達到何種程度時中止測試

暖機用來讓程式載入必要內容、建立連線並進入可比較狀態。暖機結果不應混入正式量測區間。測試是否採用已暖機或剛啟動狀態,取決於實際需求,兩者都需要時就分成不同案例。

輸入資料也要避免每次重複命中同一筆內容。可以按照已確認的熱門程度分布選取資料,並為會修改狀態的操作建立足夠且可重設的輸入,避免資料衝突改變原本要測量的處理路徑。

選擇開放式或封閉式負載模型

負載工具通常提供兩種排程觀念:k6 的工作負載模型說明Gatling 的模型說明都要求測試者按照系統實際接收工作的方式選擇。

  • 開放式模型(Open Workload Model)按照到達率(Arrival Rate)啟動新工作,不等待先前工作完成。它適合外部工作會持續到達,而且受測系統無法限制來源數量的情境。
  • 封閉式模型(Closed Workload Model)維持固定的同時執行單元,前一輪完成後才開始下一輪。它適合工作來源確實具有固定數量,或入口會先限制同時執行數的情境。

工具中的 VU 代表一個重複執行情境的單元,不必然等於一位實際操作人員。腳本等待時間、操作長度與回應速度都會影響一個 VU 能完成多少工作,不能直接把 VU 數量當成每秒操作數。

如果實際工作會持續到達,封閉式模型在系統變慢時也會降低新工作的產生速度,形成協調遺漏(Coordinated Omission)。測試結果可能顯示負載穩定,實際上只是產生器跟著受測系統一起變慢。應該以開放式模型維持指定到達率,或另外記錄原本應該到達但未送出的工作。

選擇符合情境的負載工具

工具選擇要根據受測互動方式、負載模型、腳本維護能力、結果格式與自動化需求。k6、Apache JMeter 與 Gatling 都能建立負載測試,使用方式與限制不同。

工具 腳本與模型 適合評估的情境 使用前要確認的限制
k6 使用 JavaScript 或 TypeScript 描述情境,透過 Scenario 與 Executor 控制負載,並以 Threshold 定義通過條件 希望以程式碼維護協定層或瀏覽器情境,並將門檻納入自動執行 TypeScript 執行時只移除型別資訊,不會提供完整型別檢查。大型測試也要驗證產生器容量與分散執行方式
Apache JMeter 以測試計畫樹組合取樣器、資料與判斷條件,圖形介面適合建立及除錯計畫 已有 JMX 測試計畫、需要其支援的協定或偏好圖形化建模 正式負載應使用命令列模式。大量監聽器與圖形介面會影響產生負載的能力
Gatling 支援 Java、JavaScript、TypeScript、Kotlin 與 Scala,提供開放式及封閉式注入模型與 Assertion 希望使用程式語言、建置工具與程式碼審查維護情境 各語言 SDK、協定與社群版或企業版能力不同,選擇前要核對需要的協定、報表及分散執行方式

k6 的 Threshold 文件Gatling 的 Assertion 文件都能將回應時間、錯誤比例或其他統計值轉成通過與失敗結果。JMeter 官方手冊則明確要求正式負載使用命令列模式,圖形介面只用於建立及除錯測試計畫。

選擇前可以用一個代表性情境完成概念驗證(Proof of Concept, POC),比較腳本可讀性、資料準備、負載形狀、門檻判定、原始結果匯出及失敗調查。也要讓負載產生器執行到高於預期負載,確認限制來自受測系統,而非工具執行環境。

如果測試只在協定層直接送出操作,結果不包含瀏覽器呈現與互動時間。目標需求包含操作介面時,應該分開建立瀏覽器量測或少量混合情境,並保留各自的指標與門檻。k6 的網站負載測試說明也區分協定層、瀏覽器與混合測試的量測範圍。

同時觀察對外結果與內部限制

負載工具看到的是操作開始到結果返回的時間,無法單獨指出等待發生在哪一段。測試期間要用相同時間範圍與案例識別碼,對照受測系統及相依項目的紀錄與指標。

觀察位置 建議記錄的指標 可以協助判斷的問題
負載產生器 實際到達率、同時執行數、成功與失敗數、回應時間及產生器餘裕 測試是否真的送出預定負載,產生器是否先受限
系統入口 接受、拒絕、逾時、排隊與執行時間 延遲來自等待、處理或超載保護
程式內部 各處理階段時間、工作佇列、連線池、垃圾回收與重試次數 哪一段開始飽和,重試是否放大負載
保存機制 讀寫等待、衝突、連線使用與慢操作 如果系統保存狀態,限制是否發生在保存邊界
相依項目 呼叫數、等待時間、錯誤、逾時與斷路狀態 效能問題是否由相依項目或錯誤重試造成
非同步流程 佇列深度、最舊工作等待時間、消費速率與重試數 對外操作完成後,後續工作是否持續落後
執行環境 執行資源使用率、限制與節流事件 目前設定是否已達容量限制

如果系統使用資料庫、訊息代理或跨程序呼叫,才加入相對應的連線、查詢、消費與通訊指標。通用測試清單不需要替每個系統預設這些構成。

測試結果應該使用 operationId 或案例標籤串連一次操作的負載資料、程式記錄與相依結果。只有各自獨立的平均值,很難判斷同一時間發生的延遲與錯誤是否相關。

使用百分位數判斷長尾延遲

平均回應時間會把少量極慢操作與大量快速操作混合,無法呈現大多數操作對延遲的實際感受。第 95 百分位(95th Percentile, p95)為 800 毫秒,表示量測樣本中有 95% 在 800 毫秒內完成,其餘 5% 較慢。第 99 百分位(99th Percentile, p99)則更接近長尾操作。

分析百分位數時要保持相同量測範圍:

  • 分開檢查不同功能與結果類型,避免快速的簡單操作掩蓋較慢的關鍵流程。
  • 將逾時與失敗納入結果,不能刪除最慢樣本後再宣稱百分位通過。
  • 比較相同負載階段與持續時間,避免把暖機、穩定負載及降載資料混在一起。
  • 保存原始樣本或足夠精度的統計分布,不能用各執行區段的 p95 再計算平均值。
  • 同時檢查吞吐量與錯誤比例,避免系統因拒絕大量工作而顯示較短回應時間。

最大值容易受到單一特殊事件影響,可以保留作為調查線索。驗收門檻通常應該使用與需求相符的百分位數、錯誤比例及完成量共同判斷。

找出最大穩定負載與安全容量

容量上限要透過逐步增加負載觀察,不能只執行一次極高壓力。每一個負載階段都要持續足夠時間,讓排隊、重試、垃圾回收與相依限制有機會出現。

  1. 先用少量工作確認腳本、測試資料、監控與功能判斷都正確。
  2. 完成暖機後,從一般負載開始,維持到指標進入穩定範圍。
  3. 以固定幅度提高到達率或同時執行數,並在每一階段檢查所有驗收門檻。
  4. 指標超過門檻、積壓持續成長或觸發安全停止條件時,不再提高負載。
  5. 降回一般負載,繼續觀察回應、錯誤、積壓與資料結果是否在期限內恢復。

最大穩定負載是目前版本與設定在指定持續時間內,仍能通過回應、錯誤、完成量、積壓及正確性條件的最高已驗證負載。它不代表短時間曾經接受的最高數字,也不能直接套用到不同環境或資料規模。

正式運作的安全容量應該低於最大穩定負載。保留多少餘裕要考量工作量波動、資料成長、相依項目變化、擴充所需時間與故障期間可用容量,沒有適用所有系統的固定比例。安全容量、告警門檻與重新測試條件應該一起記錄。

驗證超載時的失敗與恢復

壓力測試除了找到門檻,也要確認超過門檻後的行為可控制。系統可以按照設計拒絕、延後或降級工作,但不能在沒有明確結果的情況下遺失已接受的操作。

  • 驗證超載保護是否回覆可辨識結果,並限制新工作進入已飽和的處理範圍。
  • 驗證逾時與重試是否具有上限,避免失敗工作持續放大負載。
  • 驗證工作佇列是否有容量限制,以及超出限制後會拒絕、延後或轉移到哪裡。
  • 驗證處理中的狀態變更是否保持原子性,避免逾時後留下部分完成結果。
  • 驗證負載下降後,新操作先恢復正常,既有積壓再按照限制速度清除。
  • 驗證恢復過程沒有持續錯誤、重複外部效果或需要未記錄的人工重啟。

測試要預先設定中止條件,例如連續錯誤、等待時間、積壓或資料異常超過保護範圍。中止後仍要保存當下結果,完成必要復原與資料驗證,再開始下一次測試。

非同步流程要分開量測入口接受時間與端到端完成時間。入口快速接受只能說明工作已排入流程,還要確認消費速率、最舊工作等待時間及負載下降後的追趕時間。

以相同條件比較遺留系統與目標系統

遺留系統與目標系統要使用相同案例識別碼、操作比例、資料特徵、負載模型、測試階段與統計方式。環境無法完全相同時,應該記錄差異及其可能影響,避免直接比較兩個缺少共同基準的數字。

比較紀錄 應保存的內容
系統版本 原始碼版本、建置成品及容量相關設定
測試規格 案例識別碼、腳本版本、工具版本、資料版本與負載設定
環境條件 執行單位、容量限制、相依項目及測試期間的其他工作
對外結果 回應時間百分位、吞吐量、錯誤比例與功能結果
內部狀態 排隊、處理階段、相依等待、執行資源與積壓變化
容量結論 最大穩定負載、安全容量、第一個瓶頸及恢復時間

同一條件應該重複執行並記錄結果分布,不能只保留最好的一次。變異過大時要先找出環境、資料或背景工作的差異,再判斷版本之間的改善幅度。

目標系統不需要在每一項數字上超過遺留系統,但必須符合已核准的目標需求。任何為了效能而調整的程式、查詢、平行處理或快取,都要在相同情境下重新測試,並再次執行功能驗證,確認輸出與狀態變化沒有改變。

保存可重現的測試成果

效能測試腳本、資料產生方式與設定應該納入版本控制。每次正式結果至少要保存下列資訊:

  • 記錄受測版本、建置成品、環境設定與相依項目版本。
  • 記錄案例識別碼、腳本版本、工具版本、資料版本及實際負載階段。
  • 保存原始結果、彙整報告、系統指標與測試期間的重要事件。
  • 記錄每項門檻的通過結果、最大穩定負載、安全容量與恢復時間。
  • 記錄偏離原定情境的事項、測試中止原因及無法解釋的變異。
  • 建立可以從乾淨環境重建資料、執行測試及產生報告的操作方式。

測試規模可以分層。小型代表情境適合在一般變更後快速執行,完整負載測試可以在準備發布時執行,壓力與耐久測試則按照成本及風險定期安排。自動化流程應該使用腳本中的驗收門檻決定通過或失敗,不能只產生一份沒有人判讀的圖表。

測試結果具有環境與版本範圍。系統程式、資料規模、部署設定、相依版本或工作負載模型明顯改變時,都要重新執行相關情境,不能長期沿用過期容量。

完成效能與容量驗證的檢查

  • 是否已將預期與尖峰工作量改寫成操作比例、到達率或同時執行數、資料規模及持續時間?
  • 是否已定義回應時間百分位、吞吐量、錯誤比例、資料結果、積壓與恢復時間門檻?
  • 負載、壓力、尖峰與耐久測試是否各自具有明確目的及負載形狀?
  • 測試環境是否隔離正式操作,並記錄與預定部署環境的容量差異?
  • 遺留系統與目標系統是否使用相同案例識別碼、資料、負載模型與統計方式?
  • 工作負載模型是否符合實際到達方式,並避免協調遺漏掩蓋過載?
  • 負載產生器是否仍有足夠餘裕,且實際產生的工作量符合設定?
  • 是否同時觀察對外結果、程式內部、相依項目、積壓及執行環境指標?
  • 最大穩定負載是否在持續符合所有門檻的條件下取得?
  • 超載後是否能受控失敗,並在負載下降後於限制時間內恢復?
  • 效能調整後是否用相同條件重測,並確認功能結果仍然正確?
  • 腳本、資料、設定、原始結果、結論與重新測試條件是否可以追溯?

重點整理

  • 效能需求要包含工作負載、資料規模、持續時間、回應、完成量、錯誤、積壓與恢復條件,才能形成可執行的驗收門檻。
  • 工作負載模型應該來自實際紀錄與已核准假設,並分開描述到達率、同時執行數、操作比例及資料分布。
  • 負載、壓力、尖峰與耐久測試回答不同問題,要分別定義負載形狀、持續時間及通過條件。
  • 測試環境、資料、腳本與相依項目要可重建,遺留系統與目標系統才能使用相同條件比較。
  • 開放式與封閉式負載模型要符合工作實際到達方式,避免系統變慢時測試也自動降低輸入。
  • k6、Apache JMeter 與 Gatling 都能產生負載,選擇時要比較腳本維護、負載模型、協定、門檻判定、結果格式與執行方式。
  • 平均值不足以判斷長尾延遲,應該同時檢查百分位數、吞吐量、錯誤比例、積壓與內部限制。
  • 最大穩定負載是持續符合所有門檻的最高已驗證負載,安全容量還要保留工作波動、成長、擴充與故障所需餘裕。
  • 壓力測試要驗證系統超載時能受控失敗,並在負載下降後於限制時間內恢復正確結果。
  • 效能腳本、測試資料、原始結果與容量結論要納入版本追蹤,系統或工作負載改變後必須重新測試。

上一篇
[Day 24] 分散式服務之間的資料要如何同步?
下一篇
[Day 26] 如何減輕服務壓力?需要快取嗎?
系列文
遠古聖遺物改造工程:遺留系統全面重構實務指南30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言